home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / sbin / foomatic-addpjloptions < prev    next >
Text File  |  2009-09-18  |  30KB  |  930 lines

  1. #!/usr/bin/perl
  2.  
  3. #
  4. # This script adds PJL options, polled from the printer, into the Foomatic
  5. # database. Use "foomatic-getpjloptions" to poll the options, use
  6. # "foomatic-addpjloptions -h" for help.
  7. #
  8.  
  9. #
  10. # Till Kamppeter (till.kamppeter@gmx.net)
  11. #
  12. # Copyright 2001 Till Kamppeter
  13. #
  14. # This software may be freely redistributed under the terms of the GNU
  15. # General Public License (http://www.gnu.org/).
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software
  19. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. #
  21.  
  22. use strict;
  23. use FileHandle;
  24.  
  25. my $dir = "./foomatic-db/opt";
  26.  
  27. sub usage(){
  28.     print STDERR <<EOF;
  29. Usage: foomatic-addpjloptions [-dafis][-o option_dir] -p printer_ID [<pjl option file>]
  30.        foomatic-addpjloptions [-dqaf] [<pjl option file>]
  31.        foomatic-addpjloptions -h
  32.  
  33.    -a                 Include all options
  34.    -d                 enable debugging output
  35.    -f                 Do not ask user whether he really wants to add the
  36.                       PJL options
  37.    -i                 Include only important options
  38.    -s                 Create a single option file
  39.    -q                 Summary format
  40.    -h                 This help message
  41.    -p printer_ID      Printer where to add the PJL options
  42.    -o option_dir      directory for saving option files (default $dir)
  43.    <pjl option file>  File with the PJL options returned by the printer,
  44.                       if this filename is not provided, the PJL options are
  45.                       taken from standard input.
  46. EOF
  47.  
  48.     exit(1);
  49. }
  50.  
  51. # ignore the following entries by default
  52. my $opt = {};
  53. my $debug = 0;
  54. my $exclusions =
  55.     { 'PAPER'=>1,  # already handled by Ghostscript/PS
  56.       'RESOLUTION'=>1, # already handled by Ghostscript/PS
  57.       'LANG'=>1,       # only affects printer display
  58.       'PERSONALITY'=>1,# the page description language
  59.             # is set by the driver
  60.       'PAGECOUNT'=>1,  # printer-internal counters,
  61.       'LPAGECOUNT'=>1, # no influence on print job
  62.       'PAGES'=>1,
  63.       'MAINTINTERVAL'=>1,
  64.       'FORMLINES'=>1,  # only for text printing
  65.       'AUTOCRLF'=>1,   # but Foomatic prints text as
  66.       'AUTOLFCR'=>1,   # PostScript
  67.       'FONTSOURCE'=>1,
  68.       'FONTNUMBER'=>1,
  69.       'PITCH'=>1,
  70.       'PTSIZE'=>1,
  71.       'SYMSET'=>1,
  72.       'LFONTPRIORITY'=>1,
  73.       'POWERSAVE'=>1,  # not a per-job setting
  74.       'TIMEOUT'=>1,
  75.       'USERNAME'=>1,   # String options
  76.       'JOBNAME'=>1,
  77.       };
  78.  
  79. # important options
  80.     my $longsubs = { 
  81.     'copies' => 'Number of Copies',
  82.     'orientation' => 'Orientation',
  83.     'ret' => 'Resolution Enhancement',
  84.     'manualfeed' => 'Manual Feed of Paper',
  85.     'pageprotect' => 'Page Protection',
  86.     'mptray' => 'Multi-Purpose Tray',
  87.     'density' => 'Toner Density',
  88.     'lowtoner' => 'Behaviour when Toner Low',
  89.     'outbin' => 'Output Bin',
  90.     'joboffset' => 'Job Offset',
  91.     'economode' => 'Toner Saving',
  92.     'ecoprint' => 'Toner Saving',
  93.     'intray1size' => 'Paper Size in Tray 1',
  94.     'intray2size' => 'Paper Size in Tray 2',
  95.     'intray3size' => 'Paper Size in Tray 3',
  96.     'intray4size' => 'Paper Size in Tray 4',
  97.     'intray5size' => 'Paper Size in Tray 5',
  98.     'intray6size' => 'Paper Size in Tray 6',
  99.     'intray7size' => 'Paper Size in Tray 7',
  100.     'intray8size' => 'Paper Size in Tray 8',
  101.     'intray9size' => 'Paper Size in Tray 9',
  102.     'intray10size' => 'Paper Size in Tray 10',
  103.     'widea4' => 'Wide A4',
  104.     'bitsperpixel' => 'Bits Per Pixel',
  105.     'holdtype' => 'Hold Job Type',
  106.     'hold' => 'Hold Job',
  107.     'pr1200speed' => 'Speed at 1200 dpi',
  108.     'outbinprocess' => 'Output Bin Process',
  109.     'finish' => 'Finisher',
  110.     'stapleoption' => 'Stapling Mode',
  111.     'extendedprintarea' => 'Extended Print Area',
  112.     'heldjobtimeout' => 'Timeout for Held Jobs',
  113.     'imageadapt' => 'Image Adaptation',
  114.     'autocont' => 'Autocont',
  115.     'fastraster' => 'Fast Raster',
  116.     'intray1' => 'Input Tray 1',
  117.     'intray2' => 'Input Tray 2',
  118.     'intray3' => 'Input Tray 3',
  119.     'intray4' => 'Input Tray 4',
  120.     'intray5' => 'Input Tray 5',
  121.     'intray6' => 'Input Tray 6',
  122.     'intray7' => 'Input Tray 7',
  123.     'intray8' => 'Input Tray 8',
  124.     'intray9' => 'Input Tray 9',
  125.     'intray10' => 'Input Tray 10',
  126.     'duplex' => 'Double-Sided Printing',
  127.     'binding' => 'Binding',
  128.     'holdkey' => 'Key for Held Jobs',
  129.     'lparm_postscript_prtpserrs' => 'Print PostScript Errors',
  130.     'limageenhance' => 'Image Enhancement',
  131.     'limageenhancetype' => 'Image Enhancement Type',
  132.     'lblankpages' => 'Blank Pages',
  133.     'lcollation' => 'Collation',
  134.     'limagerotation' => 'Image Rotation',
  135.     'linmpfeedersize' => 'Paper Size in MP Feeder',
  136.     'lsubstitutesize' => 'Substitute Paper Size',
  137.     'lpicturegrade' => 'Picture Grade',
  138.     'ljamrecovery' => 'Jam Recovery',
  139.     'lpagemode' => 'Page Mode',
  140.     'lmultipageborder' => 'Border for N-up Printing',
  141.     'lmultipageorder' => 'Order for N-up Printing',
  142.     'lmultipageprint' => 'Pages per Sheet (N-up Printing)',
  143.     'lmultipageview' => 'Orientation for N-up Printing',
  144.     'lparm_pcl_lbitmaprounding' => 'Bitmap Rounding',
  145.     'lparm_pcl_lcolorextensiond' => 'Colour Extensions',
  146.     'lseparatorsheets' => 'Separator Sheets',
  147.     'lseparatorsource' => 'Take Separator Sheets From',
  148.     'econolevel' => 'Toner Saving Level',
  149.     'mediatype' => 'Media Type',
  150.     'mediasource' => 'Media Source',
  151.     'sourcetray' => 'Media Source',
  152.     'kintrayselect' => 'Media Source',
  153.     'okipaperfeed' => 'Media Source',
  154.     'lpapersource' => 'Media Source',
  155.     'errorprint' => 'Print Error Messages',
  156.     'lcolormodel' => 'Colour Model',
  157.     'lcolorcorrection' => 'Colour Correction',
  158.     'limagebrightness' => 'Image Brightness',
  159.     'limagecontrast' => 'Image Contrast',
  160.     'limagesmoothing' => 'Image Smoothing',
  161.     'lprintquality' => 'Printout Quality',
  162.     'okipapersizecheck' => 'Paper Size Checking'
  163.     #'papersize' => 'Media Size',
  164.     #'paper' => 'Media Size',
  165.     #'lang' => 'Language',
  166.     #'resolution' => 'Resolution',
  167.     #'personality' => 'Personality',
  168.     #'timeout' => 'Timeout',
  169.     #'cplock' => 'CP Lock',
  170.     #'powersave' => 'Power Saving',
  171.     #'powersavetime' => 'Power Saving Timeout',
  172.     #'iobuffer' => 'I/O Buffer',
  173.     #'iosize' => 'I/O Size',
  174.     #'resourcesave' => 'Resource Saving',
  175.     #'disklock' => 'Disk Lock',
  176.     #'qty' => 'Quantity',
  177.     #'courier' => 'Courier',
  178.     #'formlines' => 'Form Lines',
  179.     #'reprint' => 'Reprint',
  180.     #'password' => 'Password',
  181.     #'username' => 'User Name',
  182.     #'jobname' => 'Job Name',
  183.     #'testpage' => 'Test Page',
  184.     #'planesinuse' => 'Planes in Use',
  185.     #'outlinepointsize' => 'Outline Point Size',
  186.     #'maintinterval' => 'Maintenance Interval',
  187.     #'finishertype' => 'Finisher Type',
  188.     #'finisheroption' => 'Finisher Option',
  189.     #'hitransfer' => 'Hi Transfer',
  190.     #'parallel' => 'Parallel Port Mode',
  191.     #'xoffset' => 'X Offset',
  192.     #'yoffset' => 'Y Offset',
  193.     #'lpowersaver' => 'Power Saver',
  194.     #'ladvancedstatus' => 'Advanced Status',
  195.     #'lalarmcontrol' => 'Alarm Control',
  196.     #'lcancel' => 'Cancel',
  197.     #'lresourcesave' => 'Resource Saving',
  198.     #'lleftmarginoffset' => 'Left Margin Offset',
  199.     #'ltopmarginoffset' => 'Top Margin Offset',
  200.     #'okieurosign' => 'Euro Character',    
  201.     };
  202.  
  203. # Read command line options
  204. use Getopt::Std;
  205. # Printer ID, force (no printer ID confirmation)
  206. getopts("p:o:afisqh",$opt) || usage();
  207.  
  208. # Show usage info
  209. if ($opt->{h}) {
  210.     usage();
  211. }
  212. $debug = $opt->{d} if $opt->{d};
  213. if( $opt->{a} ){
  214.     $opt->{i} = 0;
  215.     $exclusions = {};
  216. }
  217.  
  218. $dir = $opt->{o} if $opt->{o};
  219.  
  220.  
  221. my $libdir = ".";
  222.  
  223. my($printer,$manufacturer,$model,$templatename);
  224. # Check presence of a printer ID
  225. if ($opt->{p}) {
  226.     $printer = $opt->{p};
  227. } elsif( not $opt->{q} ){
  228.     die "No printer ID given! Use the '-p <Foomatic printer ID>' option.";
  229. }
  230. if( $printer ){
  231.     print "# PRINTER '$printer'\n";
  232.     # Does the chosen printer ID exist in the database?
  233.     my $printerdbentryfile = `grep -l printer/$printer $libdir/db/source/printer/*.xml 2>/dev/null`
  234.         || die "No printer with the Foomatic ID $printer in the $libdir/db/source/printer/*.xml local database";
  235.     print "# Printer $printerdbentryfile\n" if $debug;
  236.     my @p = split(" ", $printerdbentryfile);
  237.     if( @p != 1 ){
  238.         print STDERR <<EOF;
  239. Multiple matches for $printer
  240. EOF
  241.         print STDERR join("\n  ",@p) . "\n";
  242.         exit 1;
  243.     }
  244.  
  245.     $manufacturer = `grep "<.*make.*>" $printerdbentryfile`;
  246.     $manufacturer =~ m!<\s*make\s*>\s*(.*)\s*<\s*/make\s*>!;
  247.     $manufacturer = $1;
  248.     $model = `grep "<.*model.*>" $printerdbentryfile`;
  249.     $model =~ m!<\s*model\s*>\s*(.*)\s*<\s*/model\s*>!;
  250.     $model = $1;
  251. }
  252.  
  253. # Check presence of the PJL option snapshot file
  254. my $snapshotfile = "STDIN";
  255. if ($ARGV[0]) {
  256.     $snapshotfile = $ARGV[0];
  257.  
  258.     # Does the chosen snapshot file exist?
  259.     if (!-f $snapshotfile) {
  260.     die "The given PJL snapshot file $snapshotfile does not exist!";
  261.     }
  262. } else {
  263.     # interactive mode not supported with PJL snapshot from STDIN
  264.     $opt->{f} = 1;
  265. }
  266.  
  267. # Tell the user what we will do
  268. if( not $opt->{q} ){
  269.     print "# The PJL options from the file $snapshotfile\n";
  270.     print "# will be added to the $manufacturer $model.\n\n";
  271. }
  272.  
  273. # Ask whether this is correct
  274. if (!$opt->{f}) {
  275.     print "Is this correct (y/n)? ";
  276.     my $input=<STDIN>;
  277.     if ($input ne "y\n") {exit 0;}
  278.     print "\n";
  279. }
  280.  
  281. # Read the PJL snapshot file
  282. my @snapshot = ();
  283. if ($snapshotfile ne "STDIN") {
  284.     open PJLSNAPSHOT, "$snapshotfile" or die "Cannot open $snapshotfile!";
  285.     @snapshot = <PJLSNAPSHOT>;
  286.     close PJLSNAPSHOT;
  287. } else {
  288.     # Read STDIN
  289.     @snapshot = <STDIN>;
  290. }
  291.  
  292. if( !$opt->{q} ){
  293.     # OK, make the db hierarchy alongside the templates one...
  294.     print "# options in directory $dir\n";
  295.     print `mkdir -p $dir` . "\n" if (not -d $dir );
  296.     die "cannot create directory $dir" if ( not -d $dir );
  297. }
  298.  
  299. # Read the options and add them to the database
  300. my $inoptionlisting = 0; # 1 if we are after a line "@PJL INFO VARIABLES"
  301.                          # and no other "@PJL ..." line appeared
  302. my $option = "";         # Name of current option
  303. my $optiontype = -1;     # 0: enum, 1: int, 2: float, -1: not found yet
  304. my $numchoices = -1;     # Number of choices, -1: not found yet
  305. my $default = "";        # Default setting
  306. my @choices = ();        # List of possible choices
  307. my $choicesfound = 0;    # How many choices were already found
  308. my $NEWF;
  309. my $outputline = "";
  310. if( $opt->{s} and not $opt->{q} ){
  311.     my $dbfilename = "foomatic-db/opt/pjl-${manufacturer}-${model}.xml";
  312.     print "# writing $dbfilename\n";
  313.     $dbfilename =~ s/\s/_/g;
  314.     $NEWF = new FileHandle  "> $dbfilename" or die "cannot open $dbfilename";
  315. }
  316. for my $line (@snapshot) {
  317.     chomp $line;
  318.     $line =~ s/\015//;
  319.     print "xxx $line\n" if $debug;
  320.     if ($line !~ m/^\s*$/) { # Ignore blank lines
  321.     if ($inoptionlisting == 0) { # Start of option block not found yet
  322.         if ($line =~ m/^\s*\@PJL\s*INFO\s*VARIABLES\s*$/) {
  323.         $inoptionlisting = 1; # Start of option block
  324.                 print "# >>> OPTION BLOCK FOUND\n";
  325.         }
  326.     } else { # we are in the option block now
  327.         if ($line =~ m/^\s*\@PJL/) {
  328.         $inoptionlisting = 0; # End of option block
  329.                 print "# >>> END OF OPTION BLOCK\n";
  330.         } elsif (
  331.             $line =~ m/^\s*([\w\s:]*)\s*=\s*\"?([\w\.\?]*)\"?\s*\[\s*([0-9]*)\s*(\w*)\s*(\w*)\]/
  332.             or
  333.             $line =~ m/^\s*([\w\s:]*)\s*=\s*\"(.*)\"\s*\[\s*(\w*)\s*\]/
  334.             #              option           default        numchoices
  335.             ) { # Option header
  336.         if ($numchoices > -1) {
  337.             print "# WARNING: Choice(s) missing, option ignored!\n";
  338.         }
  339.         if( $outputline ){
  340.             print $outputline . "\n";
  341.             $outputline = "";
  342.         }
  343.         my $typestr;
  344.                 my $modifierstr;
  345.         ($option, $default, $numchoices, $typestr, $modifierstr) = 
  346.             ($1, $2, $3, $4, $5);
  347.         if( $numchoices eq "STRING" ){
  348.                 $typestr = $numchoices;
  349.                 $numchoices = "";
  350.         }
  351.         print "# Option: '$option', Default '$default', Numchoices '$numchoices', Typestr '$typestr', Modifier '$modifierstr'\n";
  352.                 if ($modifierstr eq "READONLY") { # Ignore READONLY options
  353.             $numchoices = -2;
  354.             print "# WARNING: Read-only option, ignored!\n";
  355.         } elsif (($modifierstr eq "STRING") || ($typestr eq "STRING")) { 
  356.             if( defined $exclusions->{$option} ){
  357.             $numchoices = -2;
  358.             print "# WARNING: Option does not make sense for Foomatic, ignored!\n";
  359.                 next;
  360.             };
  361.             if( $opt->{q} ){
  362.                 my $optname = $option;
  363.                 $optname =~ s/\W/_/g;
  364.                 $outputline = $optname;
  365.                 if( $optname ne $option ){
  366.                     $optname = "($option)";
  367.                     $optname =~ s/\s/+/g;
  368.                 } else {
  369.                     $optname = "";
  370.                 }
  371.                 $outputline .= "=${optname}STRING";
  372.             }
  373.             my $shortoption = $option;
  374.             $shortoption =~ tr/A-Z :/a-z__/; # $shortoption is 
  375.                              # lowercase and without
  376.                              # spaces
  377.             my $longoption = $shortoption;
  378.             my $optionid = "pjl-$printer-$shortoption";
  379.             # Substitution list to for the menu texts of the options
  380.             # ($longoption)
  381.             # Only options of major importance are substituted, so 
  382.             # one can separate options of lower importance
  383.             # ($longoption begins with a lowercase letter) into
  384.             # an "advanced options" group. The "-i" (Important)
  385.             # option removes these options of low importance
  386.             # Do the substitutions
  387.             my $substituted = 0;
  388.             my ($substr);
  389.             for $substr (keys(%$longsubs)) {
  390.             my $substitution = $longsubs->{$substr};
  391.             if (($longoption =~ m!^$substr$!) ){
  392.                 $longoption =~ s!^$substr$!$substitution!g;
  393.                 # Remove option if not substituted and "-i"
  394.                 # flag is set (option is not "important"
  395.                 $substituted = 1;
  396.                 next;
  397.             } 
  398.             }
  399.             if( $opt->{i} and not $substituted ){
  400.             # Reset variables
  401.             $option = "";
  402.             $optiontype = -1;
  403.             $numchoices = -1;
  404.             $default = "";
  405.             @choices = ();
  406.             $choicesfound = 0;
  407.             next;
  408.             }
  409.             my $numtype = "";
  410.             my $optionsubs = 
  411.             { 'NUMTYPE' => $numtype,
  412.               'OPTIONID' => $optionid,
  413.               'SHORTOPTION' => $shortoption,
  414.               'LONGOPTION' => $longoption,
  415.               'OPTION' => $option,
  416.               'MAKE' => $manufacturer,
  417.               'MODEL' => $model,
  418.               'DEFAULT' => $default,
  419.               };
  420.             # load template file for the choice entry
  421.             $templatename = "/usr/share/foomatic/templates/pjl_string_option.xml";
  422.             open TMPL, $templatename or die "cannot open $templatename";
  423.             my @datafile = <TMPL>;
  424.             close TMPL;
  425.             my $template = join('',@datafile);
  426.             # Do the substitutions
  427.             my ($substr);
  428.             for $substr (keys(%$optionsubs)) {
  429.             my $substitution = $optionsubs->{$substr};
  430.             $template =~ s!\@\@$substr\@\@!$substitution!g;
  431.             }
  432.             # Anything not substituted?
  433.             grep (m!\@\@([^\@]+)\@\@!g
  434.               && do { warn "  Unknown substitution $1 in template file '$templatename'!\n"; },
  435.               split("\n",$template));
  436.             my $dbfilename = "foomatic-db/opt/$optionid.xml";
  437.             if( $opt->{q} ){
  438.                 print $outputline."\n" if $outputline;
  439.                 $outputline = "";
  440.             } else {
  441.                 if( not $opt->{s} ){
  442.                     $NEWF = new FileHandle  "> $dbfilename" or die "cannot open $dbfilename";
  443.                 } else {
  444.                     $dbfilename = "$optionid";
  445.                 }
  446.                 print "# writing $dbfilename...";
  447.                 print $NEWF $template;
  448.                 print " done.\n";
  449.                 if( not $opt->{s} ){
  450.                     close $NEWF;
  451.                 }
  452.             }
  453.             # Reset variables
  454.             $option = "";
  455.             $optiontype = -1;
  456.             $numchoices = -1;
  457.             $default = "";
  458.             @choices = ();
  459.             $choicesfound = 0;
  460.             next;
  461.         } elsif ($numchoices < 2) { 
  462.                                # Options with less than two choices 
  463.                                # do not make any sense, discard them
  464.             $numchoices = -2;
  465.             print "# WARNING: Less than two choices, option ignored!\n";
  466.         } else {
  467.                     # Option type 2 (float) is determined when
  468.                     # the choices are read.
  469.             my $optval = $option;
  470.             
  471.             if( $opt->{q} ){
  472.                 my $optname = $option;
  473.                 $optname =~ s/\W/_/g;
  474.                 $outputline = $optname;
  475.                 if( $optname ne $option ){
  476.                     $optname = "($option)";
  477.                     $optname =~ s/\s/+/g;
  478.                 } else {
  479.                     $optname = "";
  480.                 }
  481.                 $outputline .= "=${optname}${typestr};";
  482.             }
  483.             if ($typestr eq "ENUMERATED") {$optiontype = 0;}
  484.             elsif ($typestr eq "RANGE") {
  485.             $optiontype = 1;
  486.             # Is the default value really a number?
  487.             if ($default =~ m/[^0-9\.]/) {
  488.                 print "# WARNING: Default value for numerical option not a number, option ignored!\n";
  489.                 $numchoices = -2;
  490.                 $outputline = "";
  491.             }
  492.                     } else {
  493.             $numchoices = -2;
  494.             print "# WARNING: Unsupported option type, option ignored!\n";
  495.             }
  496.         }
  497.         if ($numchoices > -2) {
  498.             # Remove option if it is on exclusion list
  499.             # These options do not make sense for PostScript-only
  500.             # printing
  501.             if( defined $exclusions->{$option} ){
  502.                 $numchoices = -2;
  503.                 print "# WARNING: Option does not make sense for Foomatic, ignored!\n";
  504.             };
  505.             }
  506.         } elsif ($numchoices > 1) { # We have a valid option header
  507.                                 # for which not all choices are
  508.                                 # found yet
  509.         $line =~ m/^\s*(\S*)\s*$/;
  510.         my $choice = $1;
  511.         push (@choices, $choice);
  512.                 if (($optiontype == 1) && ($1 =~ /\./)) { # float option
  513.             $optiontype = 2;
  514.         }
  515.         $choicesfound ++;
  516.         if ($optiontype > 0) {
  517.             # Is the value really a number?
  518.             if ($default =~ m/[^0-9\.]/) {
  519.             print "# WARNING: Value for numerical option not a number, option ignored!\n";
  520.             $numchoices = -2;
  521.             } elsif ($choicesfound == 1) { # Minimum value
  522.             if ($default < $choice) {
  523.                 print "# WARNING: Default value out of range, option ignored!\n";
  524.                 $numchoices = -2;
  525.                 $outputline = "";
  526.             }
  527.             } elsif ($choicesfound == 2) { # Maximum value
  528.             if ($default > $choice) {
  529.                 print "# WARNING: Default value out of range, option ignored!\n";
  530.                 $numchoices = -2;
  531.                 $outputline = "";
  532.             } elsif ($choices[0] == $choices[1]) { # Max = Min?
  533.                 print "# WARNING: Maximum and minimum are equal, option ignored!\n";
  534.                 $numchoices = -2;
  535.                 $outputline = "";
  536.             }
  537.             }
  538.         }
  539.         if ($numchoices == -2) {
  540.             # Reset variables
  541.             $option = "";
  542.             $optiontype = -1;
  543.             $default = "";
  544.             @choices = ();
  545.             $choicesfound = 0;
  546.         } elsif ($choicesfound == $numchoices) { # All choices for 
  547.                                                  # the current 
  548.                                                  # option read
  549.             #print "$option, $default, $numchoices, $optiontype\n";
  550.             #print "@choices\n";
  551.             if( $opt->{q} ){
  552.             $outputline .= join(",",@choices);
  553.             }
  554.  
  555.             # Check, if the default is in the list of choices
  556.             if ($optiontype == 0) {
  557.             # Enum option: Default is in the choice list?
  558.             my $defaultfound = 0;
  559.             for $choice (@choices) {
  560.                 if ($default == $choice) {$defaultfound = 1};
  561.             }
  562.             if ($defaultfound == 0) {
  563.                 # Add default value to the list
  564.                 push(@choices, $default);
  565.                             print("# WARNING: Default added!\n");
  566.             }
  567.             }
  568.             # We have a complete option now, enter it into the
  569.             # template XML files to generate a Foomatic database
  570.             # entry
  571.             my $numtype = '';
  572.                     if ($optiontype == 2) {$numtype = "float";}
  573.             elsif ($optiontype == 1) {$numtype = "int";}
  574.                     else {$numtype = "enum";}
  575.             my $shortoption = $option;
  576.             $shortoption =~ tr/A-Z :/a-z__/; # $shortoption is 
  577.                                                      # lowercase and without
  578.                                              # spaces
  579.                     my $longoption = $shortoption;
  580.                     my $optionid = "pjl-$printer-$shortoption";
  581.             my $choiceblock = '';
  582.             my @choiceblocklist = ();
  583.                     my $max = '';
  584.                     my $min = '';
  585.             # Substitution list to for the menu texts of the options
  586.             # ($longoption)
  587.             # Only options of major importance are substituted, so 
  588.             # one can separate options of lower importance
  589.             # ($longoption begins with a lowercase letter) into
  590.             # an "advanced options" group. The "-i" (Important)
  591.             # option removes these options of low importance
  592.             # Do the substitutions
  593.             my $substituted = 0;
  594.             my ($substr);
  595.             for $substr (keys(%$longsubs)) {
  596.             my $substitution = $longsubs->{$substr};
  597.             if (($longoption =~ m!^$substr$!) ){
  598.                 $longoption =~ s!^$substr$!$substitution!g;
  599.                 # Remove option if not substituted and "-i"
  600.                 # flag is set (option is not "important"
  601.                 $substituted = 1;
  602.                 last;
  603.             } 
  604.             }
  605.             # Substitute $shortoption if it is one of the options
  606.             # of the "General" PPD section, so that CUPS and its
  607.             # graphical frontends insert it correctly
  608.             my $shortsubs = { 
  609.             'duplex' => 'Duplex',
  610.             'mediatype' => 'MediaType',
  611.             'mediasource' => 'InputSlot',
  612.             'sourcetray' => 'InputSlot',
  613.             'kintrayselect' => 'InputSlot',
  614.             'okipaperfeed' => 'InputSlot',
  615.             'lpapersource' => 'InputSlot'
  616.             };
  617.             # Do the substitutions
  618.             my $shortsubstituted = 0;
  619.             my ($substr);
  620.             for $substr (keys(%$shortsubs)) {
  621.             my $substitution = $shortsubs->{$substr};
  622.             if (($shortoption =~ m!^$substr$!) && 
  623.                 ($shortsubstituted == 0)) {
  624.                 $shortoption =~ s!^$substr$!$substitution!g;
  625.                 $shortsubstituted = 1;
  626.             } 
  627.             }
  628.             if ($optiontype == 0) {
  629.             # enumerated option, generate choice entries
  630.             for $choice (@choices) {
  631.                             # list of items to substitute in the choice 
  632.                 # template
  633.                 my $shortchoice = $choice;    
  634.                 $shortchoice =~ tr/A-Z? :/a-zX__/;#$shortchoice 
  635.                                              # is lowercase
  636.                                                  # and without 
  637.                                                  # spaces
  638.                 if ($shortchoice =~ m/X/) {
  639.                 $shortchoice = 'undef';
  640.                 }
  641.                 my $longchoice = $shortchoice;
  642.                 my $choiceid = "pjl-$printer-$shortchoice";
  643.                 if ($default == $choice) {
  644.                 $default = $choiceid;
  645.                 }
  646.                 my $longchoicesubs = { 
  647.                 'on' => 'On',
  648.                 'off' => 'Off',
  649.                 'enable' => 'Enabled',
  650.                 'disable' => 'Disabled',
  651.                 'enabled' => 'Enabled',
  652.                 'disabled' => 'Disabled',
  653.                 'yes' => 'Yes',
  654.                 'no' => 'No',
  655.                 'none' => 'None',
  656.                 'auto' => 'Automatic',
  657.                 'default' => 'Default',
  658.                 'intray' => 'Tray',
  659.                 'intray1' => 'Tray 1',
  660.                 'intray2' => 'Tray 2',
  661.                 'intray3' => 'Tray 3',
  662.                 'intray4' => 'Tray 4',
  663.                 'intray5' => 'Tray 5',
  664.                 'intray6' => 'Tray 6',
  665.                 'intray7' => 'Tray 7',
  666.                 'intray8' => 'Tray 8',
  667.                 'intray9' => 'Tray 9',
  668.                 'intray10' => 'Tray 10',
  669.                 'tray' => 'Tray',
  670.                 'tray1' => 'Tray 1',
  671.                 'tray2' => 'Tray 2',
  672.                 'tray3' => 'Tray 3',
  673.                 'tray4' => 'Tray 4',
  674.                 'tray5' => 'Tray 5',
  675.                 'tray6' => 'Tray 6',
  676.                 'tray7' => 'Tray 7',
  677.                 'tray8' => 'Tray 8',
  678.                 'tray9' => 'Tray 9',
  679.                 'tray10' => 'Tray 10',
  680.                 'upper' => 'Upper',
  681.                 'middle' => 'Middle',
  682.                 'lower' => 'Lower',
  683.                 'first' => 'First',
  684.                 'cassette' => 'Cassette',
  685.                 'manual' => 'Manual',
  686.                 'manualenvelope' => 'Manual Envelope Feeder',
  687.                 'manualpaper' => 'Manual Paper Feeder',
  688.                 'manualfeed' => 'Manual Feeder',
  689.                 'locked' => 'Locked',
  690.                 'unlocked' => 'Unlocked',
  691.                 'letter' => 'Letter',
  692.                 'legal' => 'legal',
  693.                 'a0' => 'A0',
  694.                 'a1' => 'A1',
  695.                 'a2' => 'A2',
  696.                 'a3' => 'A3',
  697.                 'a4' => 'A4',
  698.                 'a5' => 'A5',
  699.                 'a6' => 'A6',
  700.                 'a7' => 'A7',
  701.                 'a8' => 'A8',
  702.                 'a9' => 'A9',
  703.                 'a10' => 'A10',
  704.                 'b5paper' => 'B5 Paper',
  705.                 'executive' => 'Executive',
  706.                 'com10' => 'Com 10',
  707.                 'com9' => 'Com 9',
  708.                 'monarch' => 'Monarch',
  709.                 'dl' => 'DL',
  710.                 'c5' => 'C5',
  711.                 'b5' => 'B5',
  712.                 'otherenvelope' => 'Other Envelope',
  713.                 'jisb5' => 'JIS B5',
  714.                 'jisexec' => 'JIS Exec',
  715.                 'roc16k' => 'ROC 16K',
  716.                 'b5' => 'B5',
  717.                 'b5' => 'B5',
  718.                 'b5' => 'B5',
  719.                 'custom' => 'Custom Size',
  720.                 'portrait' => 'Portrait',
  721.                 'landscape' => 'Landscape',
  722.                 'light' => 'Light',
  723.                 'medium' => 'Medium',
  724.                 'dark' => 'Dark',
  725.                 'regular' => 'Regular',
  726.                 'job' => 'Job',
  727.                 'draft' => 'Draft',
  728.                 'tonersaver' => 'Toner Saving',
  729.                 'paper' => 'Paper',
  730.                 'normal' => 'Normal',
  731.                 'plain' => 'Plain',
  732.                 'bond' => 'Bond',
  733.                 'rough' => 'Rough',
  734.                 'cardstock' => 'Card Stock',
  735.                 'labels' => 'Labels',
  736.                 'transparency' => 'Transparency',
  737.                 'glossy' => 'Glossy',
  738.                 'letterhead' => 'Letter Head',
  739.                 'preprinted' => 'Preprinted',
  740.                 'colored' => 'Coloured',
  741.                 'customtype' => 'Custom Type',
  742.                 'customtype1' => 'Custom Type 1',
  743.                 'customtype2' => 'Custom Type 2',
  744.                 'customtype3' => 'Custom Type 3',
  745.                 'customtype4' => 'Custom Type 4',
  746.                 'customtype5' => 'Custom Type 5',
  747.                 'customtype6' => 'Custom Type 6',
  748.                 'customtype7' => 'Custom Type 7',
  749.                 'customtype8' => 'Custom Type 8',
  750.                 'customtype9' => 'Custom Type 9',
  751.                 'customtype10' => 'Custom Type 10',
  752.                 'envelope' => 'Envelope',
  753.                 'print' => 'Print',
  754.                 'donotprint' => 'Do Not Print',
  755.                 'ram' => 'RAM',
  756.                 'single' => 'Single',
  757.                 'continue' => 'Continue',
  758.                 'continuous' => 'Continuous',
  759.                 'stop' => 'Stop',
  760.                 'minimum' => 'Minimum',
  761.                 'moderate' => 'Moderate',
  762.                 'maximum' => 'Maximum',
  763.                 'public' => 'Public',
  764.                 'private' => 'Private',
  765.                 'store' => 'Store',
  766.                 'proof' => 'Proof',
  767.                 'half' => 'Half',
  768.                 'staple' => 'Staple',
  769.                 'one' => '1',
  770.                 'two' => '2',
  771.                 'three' => '3',
  772.                 'four' => '4',
  773.                 'five' => '5',
  774.                 'six' => '6',
  775.                 'seven' => '7',
  776.                 'eight' => '8',
  777.                 'nine' => '9',
  778.                 'ten' => '10',
  779.                 'oneangled' => 'One Angled',
  780.                 'oneopposed' => 'One Opposed',
  781.                 'option' => 'Option',
  782.                 'option1' => 'Option 1',
  783.                 'option2' => 'Option 2',
  784.                 'option3' => 'Option 3',
  785.                 'option4' => 'Option 4',
  786.                 'option5' => 'Option 5',
  787.                 'option6' => 'Option 6',
  788.                 'option7' => 'Option 7',
  789.                 'option8' => 'Option 8',
  790.                 'option9' => 'Option 9',
  791.                 'option10' => 'Option 10',
  792.                 'onehour' => '1 Hour',
  793.                 'fourhours' => '4 Hours',
  794.                 'oneday' => '1 Day',
  795.                 'oneweek' => '1 Week',
  796.                 'slow' => 'Slow',
  797.                 'fast' => 'Fast',
  798.                 'smooth' => 'Smooth',
  799.                 'short' => 'Short',
  800.                 'heavy' => 'Heavy',
  801.                 'long' => 'Long',
  802.                 'longedge' => 'Long Edge',
  803.                 'shortedge' => 'Short Edge',
  804.                 'undef' => 'Undefined'
  805.                 };
  806.                 # Do the substitutions
  807.                 my $chsubstituted = 0;
  808.                 my ($substr);
  809.                 for $substr (keys(%$longchoicesubs)) {
  810.                 my $substitution = $longchoicesubs->{$substr};
  811.                 if (($longchoice =~ m!^$substr$!) && 
  812.                     ($chsubstituted == 0)) {
  813.                     $longchoice =~ s!^$substr$!$substitution!g;
  814.                     $chsubstituted = 1;
  815.                 } 
  816.                 }
  817.                 my $choicesubs = 
  818.                 { 'CHOICE' => $choice,
  819.                   'SHORTCHOICE' => $shortchoice,
  820.                   'LONGCHOICE' => $longchoice,
  821.                   'CHOICEID' => $choiceid
  822.                   };
  823.                 # load template file for the choice entry
  824.                 open TMPL, "/usr/share/foomatic/templates/pjl_enum_choice.xml" or die "cannot open /usr/share/foomatic/templates/pjl_enum_choice.xml";
  825.                 my @datafile = <TMPL>;
  826.                 close TMPL;
  827.                 my $template = join('',@datafile);
  828.                 # Do the substitutions
  829.                 my ($substr);
  830.                 for $substr (keys(%$choicesubs)) {
  831.                 my $substitution = $choicesubs->{$substr};
  832.                 $template =~ s!\@\@$substr\@\@!$substitution!g;
  833.                 }
  834.                 # Anything not substituted?
  835.                 grep (m!\@\@([^\@]+)\@\@!g
  836.                   && do { warn "  Unknown substitution $1 in choice template file!\n"; },
  837.                   split("\n",$template));
  838.                 # Store choice entry
  839.                 push(@choiceblocklist, $template);
  840.             }
  841.             # Make the choices ready for being inserted into the
  842.                         # option file
  843.             $choiceblock = join('',@choiceblocklist);
  844.             } else {
  845.             # numeric option, set minimum and maximum
  846.             $min = $choices[0];
  847.             $max = $choices[1];
  848.             }
  849.             # Set up list of items to substitute in the template
  850.             # option files
  851.                     my $optionsubs = 
  852.             { 'NUMTYPE' => $numtype,
  853.               'OPTIONID' => $optionid,
  854.                       'SHORTOPTION' => $shortoption,
  855.                       'LONGOPTION' => $longoption,
  856.               'OPTION' => $option,
  857.               'MAKE' => $manufacturer,
  858.               'MODEL' => $model,
  859.               'DEFAULT' => $default,
  860.                       'CHOICES' => $choiceblock,
  861.                       'MAX' => $max,
  862.                       'MIN' => $min
  863.               };
  864.             # load template file for the option entry
  865.             if ($optiontype == 0) {
  866.             $templatename = "pjl_enum_option.xml";
  867.             } else {
  868.             $templatename = "pjl_num_option.xml";
  869.             }
  870.             open TMPL, "/usr/share/foomatic/templates/$templatename" or die "cannot open /usr/share/foomatic/templates/$templatename";
  871.             my @datafile = <TMPL>;
  872.             close TMPL;
  873.             my $template = join('',@datafile);
  874.             # Do the substitutions
  875.             my ($substr);
  876.             for $substr (keys(%$optionsubs)) {
  877.             my $substitution = $optionsubs->{$substr};
  878.             $template =~ s!\@\@$substr\@\@!$substitution!g;
  879.             }
  880.             # Anything not substituted?
  881.             grep (m!\@\@([^\@]+)\@\@!g
  882.               && do { warn "  Unknown substitution $1 in option template file '$templatename'!\n"; },
  883.               split("\n",$template));
  884.             # Finally, write out the new file
  885.             # Options are under opt/
  886.             # Do not write option when "-i" flag was used and
  887.             # option is not in substitution list ("important"
  888.             # option)
  889.                     if (($substituted == 1) || (!$opt->{i})) {
  890.             if( $opt->{q} ){
  891.                 print $outputline . "\n" if $outputline;
  892.                 $outputline = "";
  893.             } else {
  894.             my $dbfilename = "foomatic-db/opt/$optionid.xml";
  895.                 if( not $opt->{s} ){
  896.                     $NEWF = new FileHandle  "> $dbfilename" or die "cannot open $dbfilename";
  897.                 } else {
  898.                     $dbfilename = "$optionid";
  899.                 }
  900.                 print "# writing $dbfilename...";
  901.                 print $NEWF $template;
  902.                 print " done.\n";
  903.                 if( not $opt->{s} ){
  904.                 close $NEWF;
  905.                 }
  906.             }
  907.             } else {
  908.             print("# WARNING: Option '$option' of minor importance and \"-i\" set, option ignored!\n");
  909.             }
  910.             # Reset variables
  911.             $option = "";
  912.             $optiontype = -1;
  913.             $numchoices = -1;
  914.             $default = "";
  915.             @choices = ();
  916.             $choicesfound = 0;
  917.         }
  918.         } else { # All choices for current header are read but the
  919.              # current line is not a new header
  920.         if ($numchoices > -2) {
  921.             print "# WARNING: Too many choice lines for option '$option'!\n";
  922.             $numchoices = -2;
  923.         }
  924.         }
  925.     }
  926.     }
  927. }
  928.  
  929. exit 0;
  930.